Shell Tips

观书有会意处,题其衣裳,以记其事~

1. CMD 输出打印行数

1
[root@min]# ls | grep android | nl

2. 分割输出,每个一行

1
2
3
4
5
[root@min]# cat /tmp/test.txt 
10.0.57.24:10100
[root@liqiang.io]# cat /tmp/test.txt | tr ":" "\n"
10.0.57.24
10100

3. 正则表达式提取 IP 地址

1
2
3
4
[root@min]# cat /tmp/test.txt
10.0.57.24:10100
[root@min.io]# cat /tmp/test.txt | grep -o "[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}"
10.0.57.24

4. 引号嵌套

1)首先,在bash脚本中,有三种引号:

  • 单引号:两个单引号包围起来的字符串就是普通的字符串,它将保留原始的字面意思.
  • 双引号:两个双引号包围起来的字符串,部分特殊字符将起到它们的作用.这些特殊字符有: 美元符$, 反斜杠\, 反引号, 感叹号!.
  • 反引号:两个反引号包围起来的字符串,将作为命令来运行,执行的输出结果作为该反引号的内容,称为命令替换,它有另一种更好的写法: $(command)

2)难点:单引号中如何包含单引号?

1
2
3
4
5
6
[min@bogon:] ~ $ echo $'abc\'abc'  
abc'abc
[min@bogon:] ~ $ echo -e 'abc\x27abc'
abc'abc
[min@bogon:] ~ $ echo 'abc'\''abc'
abc'abc

第一种方法是bash特有的,$’string’ 之间到反斜杠都将转义字符,第二种方法,通过单引号的ASCII码来打印单引号,而第三种方法,则是通过截断命令,在中间插入单引号来实现。一般用第一种方法是最优雅的。

3)备忘两则

1
[min@bogon:] ~ $adb shell $'kill -9 $(ps -ef |grep "sh watcher.sh" |awk \'{print $2}\')'
1
2
3
4
5
6
7
8
9
10
11
[min@bogon:] ~ $ name=helleworld
[min@bogon:] ~ $ echo '${name}'
${name}
[min@bogon:] ~ $ echo ${name}
helleworld
[min@bogon:] ~ $ echo "echo ${name}"
echo helleworld
[min@bogon:] ~ $ echo 'echo "echo ${name}"'
echo "echo ${name}"
[min@bogon:] ~ $ echo 'echo "echo '${name}'"'
echo "echo helleworld"

5. 判断文件/文件夹是否存在

1)文件夹不存在则创建

1
2
3
4
5
if [ ! -d "/data/" ];then
mkdir /data
else
echo "文件夹已经存在"
fi

2)判断文件是否存在

1
2
3
4
5
if [ -f "/data/filename" ];then
echo "文件存在"
else
echo "文件不存在"
fi

3)文件比较符

1
2
3
4
5
6
7
8
9
10
11
12
13
-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新 [ ``"/data/file1"` `-nt ``"/data/file2"` `]
-ot 判断file1是否比file2旧 [ ``"/data/file1"` `-ot ``"/data/file2"` `]

6. 判断目录是否为空

1
2
3
4
5
6
7
BAK=/opt/sh/test
if [ "`ls -A ${BAK}`" = "" ];
then
echo "${BAK} is empty"
else
echo "${BAK} is not empty"
fi

7. Shell特殊变量

变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

8.Shell 函数

1)带返回值的函数

1
2
3
4
5
6
7
8
9
10
11
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum$anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

2)带参数的函数

1
2
3
4
5
6
7
8
9
10
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

8. grep 常见用法

1
2
3
4
-c 或 --count : 计算符合样式的列数;
-i 或 --ignore-case : 忽略字符大小写的差别;
-E 或 --extended-regexp : 将样式为延伸的正则表达式来使用;
-n 或 --line-number : 在显示符合样式的那一行之前,标示出该行的列数编号;

参考:

  1. 菜鸟教程 Shell教程

  2. shell 判断文件夹或文件是否存在

  3. Shell编程:Bash引号的那点事